#coding-utf-8
#@Time    : 2019/3/10 21:31
#@Author  : 刘云
#@Email   : wnliuyun@126.com
#@File    : week2.py.py
#@Software: PyCharm

import matplotlib.pyplot as plt
import cv2

class ImageBlur:
    def __init__(self, filePath):
        self.filePath = filePath
        #  获取图片数据
        self.data=cv2.imread(self.filePath)

    def originalShow(self):
            # 显示图像
           cv2.imshow("original", self.data)

    def  avereageBlurShow(self):
        #均值滤波
        averageData=cv2.blur(self.data,(5,5))
        cv2.imshow("mean blur",averageData)
    def gaussianBlurShow(self):
        #高斯滤波
        gaussianData=cv2.GaussianBlur(self.data,(5,5),0)
        cv2.imshow("Gaussian Blur",gaussianData)

    def medianBlurShow(self):
        # 中值滤波
        medianData=cv2.medianBlur(self.data,5)
        cv2.imshow("Median Blur",medianData)

    def sobelShow(self):
        # 转化成灰度图像
        grayData = cv2.cvtColor(self.data, cv2.COLOR_BGR2GRAY)
        # x轴的梯度分量
        # 第三和第四个参数分别是对X和Y方向的导数（即dx, dy），对于图像来说就是差分，这里1表示对X求偏导（差分），0
        # 表示不对Y求导（差分）。
        x = cv2.Sobel(grayData, cv2.CV_64F, 1, 0)
        y=cv2.Sobel(grayData,cv2.CV_64F,0,1)
        # 即Sobel函数求完导数后会有负值，还有会大于255的值。而原图像是uint8，即8位无符号数，
        # 所以Sobel建立的图像位数不够，会有截断。因此要使用16位有符号的数据类型，即cv2.CV_16S。
        absx=cv2.convertScaleAbs(x)
        # 别忘了用convertScaleAbs()
        # 函数将其转回原来的uint8形式。否则将无法显示图像，而只是一副灰色的窗口
        absy = cv2.convertScaleAbs(y)
        # 由于Sobel算子是在两个方向计算的，最后还需要用cv2.addWeighted(...)
        # 函数将其组合起来
        dst=cv2.addWeighted(absx,0.5,absy,0.5,0)
        cv2.imshow("sobel",dst)

    def candyShow(self):
        # 高斯滤波
        gaussianblurdata = cv2.GaussianBlur(self.data, (5, 5), 0)
        canny = cv2.Canny(gaussianblurdata, 50, 150)
        cv2.imshow("candy", canny)

    def rice(self):
        # 显示原图
        cv2.imshow("rice",self.data)

    def histShow(self):
        # hist=cv2.calcHist([self.data],[0],None,[256],[0,256])
        # plt.plot(hist)
        # 直方图
        plt.hist(self.data.ravel(),256)
        plt.show()

    def otsuShow(self):
        gray = cv2.cvtColor(self.data, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
        # 大津算法分割
        retval, dst=cv2.threshold(gray,0,255,cv2.THRESH_OTSU)
        cv2.namedWindow("dst", 2)   #创建一个窗口
        cv2.imshow("dst", dst)

    def riceCalculate(self):
        img = cv2.imread(ricePath)  # 导入图片，图片放在程序所在目录
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 101, 1)
        # 形态学去噪
        element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
        # 开运算去噪
        dst = cv2.morphologyEx(dst, cv2.MORPH_OPEN, element)
        binary, contours, hierarchy = cv2.findContours(dst, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        cv2.drawContours(dst, contours, -1, (120, 0, 0), 2)  # 绘制轮廓
        count = 0  # 米粒总数
        ares_avrg = 0  # 米粒平均
        for cont in contours:
            ares = cv2.contourArea(cont)  # 计算包围性状的面积
            if ares < 50:
                continue
            count += 1  # 总计数加1
            ares_avrg += ares
            print("{}-blob:{}".format(count, ares), end="  ")  # 打印出每个米粒的面积
            x, y, w, h = cv2.boundingRect(cont)  # 提取矩形坐标
            print("x:{} y:{}".format(x, y))  # 打印坐标
            cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0xff), 1)  # 绘制矩形
            y = 10 if y < 10 else y  # 防止编号到图片之外
            cv2.putText(img, str(count), (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1)  # 在米粒左上角写上编号
        print("米粒平均面积:{}".format(round(ares_avrg / ares, 2)))  # 打印出每个米粒的面积
        cv2.namedWindow("imagshow", 2)  # 创建一个窗口
        cv2.imshow('imagshow', img)  # 显示原始图片

        cv2.namedWindow("dst", 2)  # 创建一个窗口
        cv2.imshow("dst", dst)  # 显示灰度图



filePath="C:\\Users\\yun\\Desktop\\lena.jpg"
imageBlur =  ImageBlur(filePath)
imageBlur.originalShow()
imageBlur.avereageBlurShow()
imageBlur.medianBlurShow()
imageBlur.gaussianBlurShow()
imageBlur.sobelShow()
imageBlur.candyShow()

ricePath="C:\\Users\\yun\\Desktop\\rice.jpg"
riceObject =  ImageBlur(ricePath)
riceObject.rice()
riceObject.histShow()
riceObject.otsuShow()
riceObject.riceCalculate()



cv2.waitKey(0)
cv2.destroyAllWindows()